#include <iostream>

#include <amo/json.hpp>
#include <gtest/gtest.h>
#include <amo/path.hpp>
#include <string.hpp>
#include <amo/jsondb.hpp>
#include <amo/timer.hpp>
#include <amo/impl/basic_jsondb_pool.hpp>
#include <amo/utility.hpp>
//
//TEST(jsondb, constructor) {
//
//    amo::path::set_work_path_to_app_path();
//    amo::timer t;
//    int index = 0;
//    amo::jsondb db(L"test.db");
//    std::cout << index++ << ", read " << t.elapsed() << std::endl;
//    t.restart();
//
//    if (!db.is_open()) {
//        return  ;
//    }
//
//    amo::json table_info;
//    table_info.set_array();
//    table_info.push_back("name");
//    table_info.push_back("score");
//    table_info.push_back("age");
//    table_info.push_back("createtimestamp");
//    table_info.push_back("updatetimestamp");
//
//    if (!db.constains_table("test1")) {
//        db.create_table("test1", table_info);
//    }
//
//    db.create_table("test1", table_info);
//    amo::json val;
//    val.put("name", "test");
//    val.put("age", 32);
//    val.put("score", 99.3);
//    val.put("createtimestamp", amo::utils::now());
//
//    for (int i = 0; i < 10000000; ++i) {
//        val.put("updatetimestamp", amo::utils::now());
//        db.insert("test1", val);
//    }
//
//    std::cout << index++ << ", insert " << t.elapsed() << std::endl;
//    t.restart();
//
//    int nCount = 0;
//    int64_t timestamp = amo::utils::now();
//
//    db.query("test1", [&](const amo::jsondb::data & data)->int {
//
//        if (data.get("updatetimestamp").get<int64_t>() + 2 > timestamp) {
//            ++nCount;
//        }
//        return amo::loop_continue;
//    });
//    std::cout << index++ << ", query " << nCount << ", " << t.elapsed() <<
//              std::endl;
//    t.restart();
//    nCount = 0;
//
//    db.remove("test1", [&](const amo::jsondb::data & data)->int {
//        if (data.get("updatetimestamp").get<int64_t>() + 2 > timestamp) {
//            ++nCount;
//            return amo::loop_hit;
//        }
//
//        return amo::loop_continue;
//    });
//    std::cout << index++ << ", remove " << nCount << ", " << t.elapsed() <<
//              std::endl;
//    t.restart();
//    nCount = 0;
//
//    db.update("test1", [&](const amo::jsondb::data & data)->int {
//        data.get("updatetimestamp").put(0);
//        ++nCount;
//        return amo::loop_continue;
//    });
//    std::cout << index++ << ", update " << nCount << ", " << t.elapsed() <<
//              std::endl;
//    t.restart();
//
//    db.flush();
//    std::cout << index++ << ", write " << t.elapsed() << std::endl;
//
//
//    db.create_table("test2", table_info);
//    db.flush();
//    t.restart();
//    return ;
//
//}


TEST(jsondb, constructor2) {

    try {
    
        amo::path::set_work_path_to_app_path();
        amo::timer t;
        amo::json json2;
        json2.parse("5A105E8B9D40E1329780D62EA2265D8A/5A105E8B9D40E1329780D62EA2265D8A.0");
        /*     json2.parse("5A105E8B9D40E1329780D62EA2265D8A/5A105E8B9D40E1329780D62EA2265D8A.1");
             json2.parse("5A105E8B9D40E1329780D62EA2265D8A/5A105E8B9D40E1329780D62EA2265D8A.2");
             json2.parse("5A105E8B9D40E1329780D62EA2265D8A/5A105E8B9D40E1329780D62EA2265D8A.3");*/
        std::cout << ", read " << t.elapsed() << std::endl;
        t.restart();
        int index = 0;
        
        std::shared_ptr<  amo::basic_jsondb_pool<amo::string_coding_ansi> > pool(
            new  amo::basic_jsondb_pool<amo::string_coding_ansi>());
        amo::jsondb db(L"test2.db", false);
        db.attach(pool);
        
        std::cout << index++ << ", read " << t.elapsed() << std::endl;
        t.restart();
        
        if (!db.is_open()) {
            return ;
        }
        
        amo::json table_info;
        table_info.set_array();
        table_info.push_back("name");
        table_info.push_back("score");
        table_info.push_back("age");
        table_info.push_back("createtimestamp");
        table_info.push_back("updatetimestamp");
        table_info.push_back("arr");
        
        if (!db.constains_table("test1")) {
            db.create_table("test1", table_info);
        }
        
        //db.create_table("test1", table_info);
        amo::json val;
        val.put("name", "test");
        val.put("age", 32);
        val.put("score", 99.3);
        val.put("createtimestamp", amo::utils::now());
        amo::json arr;
        arr.set_array();
        
        for (int i = 0; i < 10 ; ++i) {
            arr.push_back(1000);
        }
        
        /*
           for (int i = 0; i < 10; ++i) {
        	   amo::json arr2;
        	   arr2.set_array();
        
        	   for (int i = 0; i < 30000; ++i) {
        		   val.put("updatetimestamp", amo::utils::now());
        		   val.put("arr", arr);
        		   arr2.push_back(val);
        
        	   }
        
        	   db.insert("test1", arr2);
           }
           */
        
        db.flush();
        std::cout << index++ << ", insert " << t.elapsed() << std::endl;
        t.restart();
        
        int64_t timestamp = amo::utils::now() - 200;
        int nCount = 0;
        
        db.query("test1", [&](const amo::jsondb::data & data)->int {
            //std::cout << data.table_value.to_string() << std::endl;
            ++nCount;
            
            /*   if (data[4].get<int64_t>() > timestamp) {
                   ++nCount;
               }*/
            
            /* if (nCount % 100000 == 0) {
                 std::cout << nCount << std::endl;
             }*/
            return amo::loop_continue;
        });
        
        
        std::cout << index++ << ", query " << nCount << ", " << t.elapsed() <<
                  std::endl;
        t.restart();
        nCount = 0;
        
        db.remove("test1", [&](const amo::jsondb::data & data)->int {
            ++nCount;
            //std::cout << data.table_value.to_string() << std::endl;
            
            /*    if (data.get("updatetimestamp").get<int64_t>() > timestamp) {
                    ++nCount;
                    return amo::loop_hit;
                }*/
            
            return amo::loop_continue;
        });
        std::cout << index++ << ", remove " << nCount << ", " << t.elapsed() <<
                  std::endl;
        t.restart();
        nCount = 0;
        
        /* db.update("test1", [&](const amo::jsondb::data & data)->int {
             data.get("updatetimestamp").put(0);
             ++nCount;
             return amo::loop_hit;
         });*/
        std::cout << index++ << ", update " << nCount << ", " << t.elapsed() <<
                  std::endl;
        t.restart();
        
        
        std::cout << index++ << ", write " << t.elapsed() << std::endl;
        
        
        db.create_table("test2", table_info);
        db.flush();
        t.restart();
        
        
        return ;
        
    } catch (const std::exception& e) {
        std::cout << e.what() << std::endl;
    }
}
